package com.insight.common.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;

/**
 * T018: AES-256 密码加密工具类
 * 用于加密和解密数据源密码等敏感信息
 * <p>
 * 加密算法: AES-256-ECB
 * 编码: Base64
 * </p>
 */
@Slf4j
public class EncryptionUtil {

    private static final String ALGORITHM = "AES";
    private static final String TRANSFORMATION = "AES/ECB/PKCS5Padding";
    private static final int KEY_SIZE = 256;

    /**
     * 默认加密密钥（生产环境应从配置文件或密钥管理服务读取）
     * 长度必须为32字节（256位）
     */
    private static final String DEFAULT_SECRET_KEY = "insight-default-encryption-key-32chars!!"; // 32字符

    /**
     * 加密字符串
     *
     * @param plainText 明文
     * @return Base64编码的密文
     */
    public static String encrypt(String plainText) {
        return encrypt(plainText, DEFAULT_SECRET_KEY);
    }

    /**
     * 加密字符串（使用自定义密钥）
     *
     * @param plainText 明文
     * @param secretKey 密钥（长度必须为16/24/32字节）
     * @return Base64编码的密文
     */
    public static String encrypt(String plainText, String secretKey) {
        try {
            SecretKeySpec key = new SecretKeySpec(getKeyBytes(secretKey), ALGORITHM);
            Cipher cipher = Cipher.getInstance(TRANSFORMATION);
            cipher.init(Cipher.ENCRYPT_MODE, key);

            byte[] encrypted = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
            return Base64.encodeBase64String(encrypted);
        } catch (Exception e) {
            log.error("Failed to encrypt text", e);
            throw new RuntimeException("Encryption failed", e);
        }
    }

    /**
     * 解密字符串
     *
     * @param cipherText Base64编码的密文
     * @return 明文
     */
    public static String decrypt(String cipherText) {
        return decrypt(cipherText, DEFAULT_SECRET_KEY);
    }

    /**
     * 解密字符串（使用自定义密钥）
     *
     * @param cipherText Base64编码的密文
     * @param secretKey  密钥（长度必须为16/24/32字节）
     * @return 明文
     */
    public static String decrypt(String cipherText, String secretKey) {
        try {
            SecretKeySpec key = new SecretKeySpec(getKeyBytes(secretKey), ALGORITHM);
            Cipher cipher = Cipher.getInstance(TRANSFORMATION);
            cipher.init(Cipher.DECRYPT_MODE, key);

            byte[] decrypted = cipher.doFinal(Base64.decodeBase64(cipherText));
            return new String(decrypted, StandardCharsets.UTF_8);
        } catch (Exception e) {
            log.error("Failed to decrypt text", e);
            throw new RuntimeException("Decryption failed", e);
        }
    }

    /**
     * 生成随机AES密钥
     *
     * @return Base64编码的密钥
     */
    public static String generateKey() {
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM);
            SecureRandom secureRandom = new SecureRandom();
            keyGenerator.init(KEY_SIZE, secureRandom);

            SecretKey secretKey = keyGenerator.generateKey();
            return Base64.encodeBase64String(secretKey.getEncoded());
        } catch (Exception e) {
            log.error("Failed to generate key", e);
            throw new RuntimeException("Key generation failed", e);
        }
    }

    /**
     * 获取密钥字节数组（确保长度为32字节）
     *
     * @param secretKey 密钥字符串
     * @return 32字节的密钥数组
     */
    private static byte[] getKeyBytes(String secretKey) {
        byte[] keyBytes = secretKey.getBytes(StandardCharsets.UTF_8);

        // 如果密钥长度不足32字节，填充到32字节
        if (keyBytes.length < 32) {
            byte[] paddedKey = new byte[32];
            System.arraycopy(keyBytes, 0, paddedKey, 0, keyBytes.length);
            return paddedKey;
        }

        // 如果密钥长度超过32字节，截取前32字节
        if (keyBytes.length > 32) {
            byte[] truncatedKey = new byte[32];
            System.arraycopy(keyBytes, 0, truncatedKey, 0, 32);
            return truncatedKey;
        }

        return keyBytes;
    }

    /**
     * 判断字符串是否为加密字符串（简单检查是否为Base64格式）
     *
     * @param text 待检查的字符串
     * @return true 如果可能是加密字符串
     */
    public static boolean isEncrypted(String text) {
        if (text == null || text.isEmpty()) {
            return false;
        }
        return Base64.isBase64(text);
    }

    /**
     * 私有构造函数，防止实例化
     */
    private EncryptionUtil() {
        throw new UnsupportedOperationException("Utility class cannot be instantiated");
    }
}
